package org.test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 处理GPS轨迹数据
 */
public class GPSTraceProcessor {
    public static GPSRange getGPSRanges(Collection<GPSPoint> traces) {
        double minLng = 180, maxLng = 0; //经度
        double minLat = 90, maxLat = 0; //纬度
        for (GPSPoint point : traces) {
            minLng = Math.min(minLng, point.lng);
            maxLng = Math.max(maxLng, point.lng);
            minLat = Math.min(minLat, point.lat);
            maxLat = Math.max(maxLat, point.lat);
        }
        return new GPSRange(minLng, maxLng, minLat, maxLat);
    }

    public static GPSTransformResult gpsToCV2(Collection<GPSPoint> traces, double tillWidth, double scale, int memoryLimit) {
        GPSRange range = getGPSRanges(traces);
        GPSPoint srcPt = new GPSPoint(range.minLng, range.minLat);

        double rightBottomY = GPSUtils.distance(new GPSPoint(range.maxLng, range.minLat), new GPSPoint(range.maxLng, range.maxLat));
        double rightBottomX = GPSUtils.distance(new GPSPoint(range.minLng, range.maxLat), new GPSPoint(range.maxLng, range.maxLat));

        scale = Math.min(scale, Math.sqrt((double) memoryLimit * 1024 * 1024 / (rightBottomX * rightBottomY)));
        scale = Math.ceil(tillWidth * scale) / tillWidth;
        int adjTillWidth = (int) (tillWidth * scale);

        if (adjTillWidth % 2 != 0) {
            adjTillWidth += 1;
            scale = (double) adjTillWidth / tillWidth;
        }

        int originShift = adjTillWidth / 2 + 1;
        double maxPointX = originShift + scale * rightBottomX;
        double maxPointY = originShift + scale * rightBottomY;

        List<GPSPoint> results = new ArrayList<>();
        for (GPSPoint g : traces) {
            GPSPoint xrefPt = new GPSPoint(range.minLng, g.lat);
            double x = GPSUtils.distance(g, xrefPt) * scale + originShift;
            GPSPoint yrefPt = new GPSPoint(g.lng, range.minLat);
            double y = GPSUtils.distance(g, yrefPt) * scale + originShift;
            results.add(new GPSPoint(x, y));
        }

        return new GPSTransformResult(results, srcPt, maxPointX, maxPointY, scale, originShift, adjTillWidth);
    }
}
